package com.wang.judge.rabbit;

import com.wang.api.domain.JudgeSubmitDTO;
import com.wang.common.redis.service.RedisService;
import com.wang.judge.service.IJudgeService;
import com.wang.common.core.constants.RabbitMQConstants;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;

import static com.wang.common.core.constants.Constant.MESSAGE_PROCESSED_ERROR;

@Component
@Slf4j
public class JudgeConsumer {

    @Autowired
    private IJudgeService judgeService;

    @Autowired
    private RedisService redisService;

    /**
     * 监听消息队列,把消息提交到指定的接口中去
     *      1.消息监听: 通过@RabbitListener注解自动监听指定队列
     *      2.消息处理: 将接收到的JudgeSubmitDTO对象传递给判题服务进行处理
     * @param judgeSubmitDTO 用户提交的代码
     */
    @RabbitListener(queues = RabbitMQConstants.OJ_WORK_QUEUE)
    public void consume(JudgeSubmitDTO judgeSubmitDTO){
        String messageId = judgeSubmitDTO.getMessageId();
        if (messageId == null) {
            log.error("消息 ID 为空，忽略该消息: {}", judgeSubmitDTO);
            return;
        }
        // 检查消息 ID 是否已经处理过
        Boolean exists = redisService.hasKey(messageId);
        if (exists != null && exists) {
            log.info("消息 ID {} 已处理过，忽略该消息", messageId);
            return;
        }
        try {
            log.info("收到消息为: {}", judgeSubmitDTO);

            //调用判题服务的 doJudgeJavaCode 方法处理消息.
            judgeService.doJudgeJavaCode(judgeSubmitDTO);

            //标记消息为已处理 (将消息id存入redis)
            //将消息id作为键,处理状态作为值存储到缓存中,过期时间为1小时.
            redisService.setCacheObject(messageId, "processed", 60L, TimeUnit.MINUTES);

        } catch (Exception e) {
            //如果消息处理异常 --> 打印日志抛出异常
            log.error("处理消息 ID {} 时发生异常", messageId, e);
            throw new RuntimeException(MESSAGE_PROCESSED_ERROR, e);
        }
    }
}
